﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace Sublimation
{
    public class EnemyUnit : Unit
    {
        // the animation
        protected AnimatedSprite.AnimatedTexture textureAnimator;
        
        protected int scoreValue;
        protected EnemyKind kind;
        public EnemyKind Kind
        {
            get { return kind; }
        }

        public virtual void setProperties()
        {
            Life = 10;
            MaxSpeed = 80f;
            MeleeDamage = 20;
            MeleeAttackDelay = 1000;
        }

        public EnemyUnit(WorldProperties worldProperties)
            : base(worldProperties)
        { 
            LoadContent();
            setProperties();
            worldProperties.EnemyCount++;

            scoreValue = 10;
            // make sure it loads and draws
            DrawOrder = 50;
            UpdateOrder = 50;
            Visible = true;
            Enabled = true;

            SetOriginToCentre();
            
            // place the unit just outside the map somewhere
            //XXX:this could update to include map spawning points etc, maybe some units jump into the play field
            int perimeterPosition = worldProperties.Random.Next(0, worldProperties.Map.Perimeter);
            if (perimeterPosition <= worldProperties.Map.WorldBounds.Width)
            {
                // place on the top
                Position = new Vector2(worldProperties.Map.WorldBounds.X + perimeterPosition, worldProperties.Map.WorldBounds.Y + 1);
            }
            else if (perimeterPosition <= worldProperties.Map.WorldBounds.Width + worldProperties.Map.WorldBounds.Height)
            {
                // right side
                perimeterPosition -= worldProperties.Map.WorldBounds.Width;
                Position = new Vector2(worldProperties.Map.WorldBounds.X + worldProperties.Map.WorldBounds.Width - 1, worldProperties.Map.WorldBounds.Y + perimeterPosition);
            }
            else if (perimeterPosition <= worldProperties.Map.WorldBounds.Width * 2 + worldProperties.Map.WorldBounds.Height)
            {
                // bottom side
                perimeterPosition -= worldProperties.Map.WorldBounds.Width + worldProperties.Map.WorldBounds.Height;
                Position = new Vector2(worldProperties.Map.WorldBounds.X + perimeterPosition, worldProperties.Map.WorldBounds.Y + worldProperties.Map.WorldBounds.Height - 1);
            }
            else
            {
                // left side
                perimeterPosition -= worldProperties.Map.WorldBounds.Width * 2 + worldProperties.Map.WorldBounds.Height;
                Position = new Vector2(worldProperties.Map.WorldBounds.X + 1, worldProperties.Map.WorldBounds.Y + perimeterPosition);
            }

            //TODO: make this real based on type
            Life = 10;
            MaxSpeed = 85f;
            MaxTurnRadiansPerSec = 0.55f;
            MeleeDamage = 20;
            MeleeAttackDelay = 1000;
            //shield = new Shield(worldProperties, this, 30, 30, 5, 1);

            // give the unit a direction
            velocity = Vector2.Zero;
            //XXX:for now just head for the centre of the map (roughly)
            velocity = new Vector2(
                worldProperties.Map.WorldBounds.Width / 2 + worldProperties.Map.WorldBounds.X + worldProperties.Random.Next(0, 50),
                worldProperties.Map.WorldBounds.Height / 2 + worldProperties.Map.WorldBounds.Y + worldProperties.Random.Next(0, 50))
                - Position;
            velocity.Normalize();
            velocity *= MaxSpeed;
        }

        //TODO: Update this to use a texture strip and the animated texture stuff.
        protected bool left = true;
        protected const int MOVE_FRAMES = 9;
        protected int lastFrames = 0;
        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            // update the animation
            textureAnimator.UpdateFrame((float)gameTime.ElapsedGameTime.TotalSeconds);
        }

        protected override void LoadContent()
        {
            base.LoadContent();

            CollisionRadius = 16f;
        }

        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);
           
            textureAnimator.Origin = Origin;
            textureAnimator.Rotation = Rotation-MathHelper.PiOver2;
            spriteBatch.Begin();
            textureAnimator.DrawFrame(spriteBatch, Position);
            spriteBatch.End();
        }

        public override void Kill()
        {
                base.Kill();

                // spawn an explosion if we died from loss of life
                if (Life <= 0) new Animation(worldProperties, this, 1.0f, 5, 10, "Sprites\\explosion");
                //if(Life <= 0) new Explosion(worldProperties, this, 1.0f);
                worldProperties.Score += scoreValue;
                // reduce enemy count
                worldProperties.EnemyCount--;
        }

        public override void GarbageCollect()
        {
            base.GarbageCollect();

            // remove from enemies list
            worldProperties.Enemies.Remove(this);
        }

        protected override void collideWithTower(Tower tower, GameTime gameTime)
        {
            base.collideWithTower(tower, gameTime);

            // damage tower
            MeleeAttack(tower);
        }

        protected const float EnemyUnitGoalBehaviourWeight = 1.0f;
        protected override void SetupBehaviours()
        {
            base.SetupBehaviours();

            this.behaviours.Add(new Behaviours.EnemyUnitGoalBehaviour(worldProperties, this, EnemyUnitGoalBehaviourWeight));

            AISightRange = 300.0f;
        }
    }
}
